package org.btik.light.server.platform.common.tool;

import org.btik.light.tool.ByteUtil;
import org.springframework.beans.BeanUtils;

import java.security.SecureRandom;
import java.util.Comparator;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * 提供依赖了spring的工具栏
 *
 * @author lustre
 * @since 2023/6/12 17:59
 */
public class PlatformTool {


    /**
     * @param t           复制源
     * @param newFunction 一般是构建构造函数
     * @return 新建对象并将复制源的属性到新建对象
     */
    public static <ResultType, T> ResultType map(T t, Supplier<ResultType> newFunction) {
        ResultType result = newFunction.get();
        BeanUtils.copyProperties(t, result);
        return result;
    }

    /**
     * @param newFunction 一般是构建构造函数
     * @return 返回一个函数，接收需要转换的对象，复制它的属性到新的对象。
     */
    public static <ResultType, T> Function<T, ResultType> mapFunction(Supplier<ResultType> newFunction) {
        return (type) -> {
            ResultType result = newFunction.get();
            BeanUtils.copyProperties(type, result);
            return result;
        };
    }

    /**
     * 按实例的属性倒序排序
     *
     * @param <U>  必须为Comparable
     * @param <T>  实体类
     * @param prop 实体类get方法，用于获取实例的某属性，本方法再以此属性排序
     */
    public static <T, U extends Comparable<? super U>> Comparator<T> orderDescBy(Function<? super T, ? extends U> prop) {
        return (obj1, obj2) -> prop.apply(obj2).compareTo(prop.apply(obj1));
    }

    /**
     * 按实例的属性正序排序
     *
     * @param <U>  必须为Comparable
     * @param <T>  实体类
     * @param prop 实体类get方法，用于获取实例的某属性，本方法再以此属性排序
     */
    public static <T, U extends Comparable<? super U>> Comparator<T> orderAscBy(Function<? super T, ? extends U> prop) {
        return Comparator.comparing(prop);
    }

    /**
     * @param passwordSource 多段源 如 {"123" ,"abc"} 则会一定从每段中取出元素来生成
     */
    public static byte[] generatePassword(String[] passwordSource, int length) {
        SecureRandom secureRandom = new SecureRandom(ByteUtil.toByteArray(System.currentTimeMillis()));
        int startIndex = secureRandom.nextInt(passwordSource.length);
        byte[] password = new byte[length];
        for (int i = 0; i < length; i++) {
            int index = startIndex++ % passwordSource.length;
            String digest = passwordSource[index];
            password[i] = (byte) digest.charAt(secureRandom.nextInt(digest.length()));

        }
        return password;
    }

    /**
     * @param passwordSource 多段源 如 {"123" ,"abc"} 则会一定从每段中取出元素来生成
     */
    public static String generatePasswordStr(String[] passwordSource, int length) {
        return new String(generatePassword(passwordSource, length));
    }

}
